package engine

import (
	"fmt"
	"miniDW/src/interfaces"
	"miniDW/src/log"
	"miniDW/src/plugins"
	"sync"
)

type Engine struct {
	createFuncs map[string]interfaces.CreateComponentFunction
}

func (e *Engine) RegisterFunction(kind string, operator string, provider string, function interfaces.CreateComponentFunction) {
	key := kind + "|" + operator + "|" + provider
	if _, ok := e.createFuncs[key]; ok {
		log.Debug("function %s already exists", key)
		return
	}
	e.createFuncs[key] = function
}

func (e *Engine) CreateFunction(kind string,
	operator string,
	provider string,
	params map[string]interface{}) (interfaces.IComponentFunction, error) {
	key := kind + "|" + operator + "|" + provider
	if createFunc, ok := e.createFuncs[key]; ok {
		function, err := createFunc(params)
		if err != nil {
			return nil, err
		}
		return function, nil
	}
	return nil, log.Error(fmt.Errorf("function %s not exists", key))
}

var (
	instance *Engine
	mu       sync.Mutex
	created  bool
)

func GetInstance() *Engine {
	mu.Lock()
	defer mu.Unlock()
	if instance == nil {
		if !created {
			instance = new(Engine)
			instance.createFuncs = make(map[string]interfaces.CreateComponentFunction)
			plugins.InitComponents(instance)
			created = true
		}
	}
	return instance
}
